package com.yylc.cscore.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import com.yylc.cif.common.service.model.UserInfo;
import com.yylc.common.lang.CollectionUtils;
import com.yylc.cscore.bean.TaskBean;
import com.yylc.cscore.bean.TaskLabelBean;
import com.yylc.cscore.bean.base.PageBean;
import com.yylc.cscore.bean.query.ServiceTaskQueryBean;
import com.yylc.cscore.dao.*;
import com.yylc.cscore.entity.Category;
import com.yylc.cscore.entity.CustomerEntity;
import com.yylc.cscore.entity.TaskEntity;
import com.yylc.cscore.entity.TaskLabelEntity;
import com.yylc.cscore.integration.UserQueryServiceClient;
import com.yylc.cscore.service.TaskService;
import com.yylc.cscore.util.PageUtil;
import com.yylc.cscore.util.R;
import com.yylc.cscore.util.YYlcBeanUtils;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.TreeSet;

import static java.util.stream.Collectors.toList;

/**
 * @author xiangnan
 * date 2018/5/8
 */
@Service
public class TaskServiceImpl implements TaskService {
    private static final Logger logger = LogManager.getLogger();

    @Resource
    private TaskDao taskDao;

    @Resource
    private TaskLabelDao taskLabelDao;

    @Resource
    private TaskRelationDao taskRelationDao;

    @Resource
    private UserBasicDataDao userBasicDataDao;

    @Resource
    private CustomerDao customerDao;

    @Resource
    private UserQueryServiceClient userQueryServiceClient;

    @Override
    public PageBean<TaskBean> serviceTaskQuery(ServiceTaskQueryBean queryBean) {

        if (StrUtil.isBlank(queryBean.getUserId()) && StrUtil.isNotBlank(queryBean.getUserPhone())) {
            UserInfo userInfo = userQueryServiceClient.queryByUserCell(queryBean.getUserPhone());
            if (userInfo == null) {
                throw new RuntimeException("通过手机未找到用户信息");
            }
            queryBean.setUserId(userInfo.getUserId());
        }

        // 获取size start
        int size = queryBean.getSize();
        int start = PageUtil.getStart(queryBean.getCurrent(), queryBean.getSize());
        queryBean.setStart(-1);

        List<TaskEntity> entityList = taskDao.selectByQueryBean(queryBean);
        int total = entityList.size();
        if (!PageUtil.check(queryBean.getCurrent(), total, size)) {
            throw new RuntimeException("页数错误");
        }

        // 标签排序
        if (StrUtil.isNotBlank(queryBean.getTaskLabel())) {
            entityList = sortByLabel(entityList, queryBean.getTaskLabel(),
                    StrUtil.isBlank(queryBean.getTaskLabelSort()) ? "" : queryBean.getTaskLabelSort());
        }

        // 服务标定查找
        if (StrUtil.isNotBlank(queryBean.getUserLabel())) {
            entityList = sortByUserLabel(entityList, queryBean.getUserLabel());
        } else {
            entityList.forEach(item -> item.setUserLabel(taskLabelDao.selectUserLabel(item.getUserId())));
        }

        // 分页
        entityList = CollectionUtil.sub(entityList, start, start + size);

        List<TaskBean> beanList = new ArrayList<>();
        if (CollectionUtil.isNotEmpty(entityList)) {
            entityList.forEach(entity -> {
                TaskBean bean = YYlcBeanUtils.copyProperties(entity, new TaskBean());
                bean.setUserInfo(userBasicDataDao.selectByUserId(bean.getUserId()));
                beanList.add(bean);
            });
        }

        return new PageBean<>(queryBean.getCurrent(), queryBean.getSize(), total, beanList);
    }

    /**
     * 根据标签和标签排序规则进行排序
     */
    private List<TaskEntity> sortByLabel(List<TaskEntity> entityList, String label, String labelSort) {

        // list1包含标签，list2不包含标签
        List<TaskEntity> list1 = new ArrayList<>();
        List<TaskEntity> list2 = new ArrayList<>();
        entityList.forEach(e -> {
            if (StrUtil.isNotBlank(e.getTaskMessage()) && e.getTaskMessage().contains(label)) {
                list1.add(e);
            } else {
                list2.add(e);
            }
        });

        if (StrUtil.equals(labelSort, "up") || StrUtil.equals(labelSort, "down")) {
            list1.sort((e1, e2) -> {
                String v1 = StrUtil.subBetween(e1.getTaskMessage() + "|", label + ":", "|");
                String v2 = StrUtil.subBetween(e2.getTaskMessage() + "|", label + ":", "|");
                try {
                    return StrUtil.equals(labelSort, "up") ?
                            Double.valueOf(v1).compareTo(Double.valueOf(v2)) : Double.valueOf(v2).compareTo(Double.valueOf(v1));
                } catch (Exception e) {
                    return StrUtil.equals(labelSort, "up") ?
                            v1.compareTo(v2) : v2.compareTo(v1);
                }
            });
        }

        list1.addAll(list2);
        return list1;
    }

    /**
     * 根据服务标定查找
     */
    private List<TaskEntity> sortByUserLabel(List<TaskEntity> entityList, String userLabel) {

        // list1包含标签，list2不包含标签，提高查找效率
        List<TaskEntity> list1 = new ArrayList<>();
        List<TaskEntity> list2 = new ArrayList<>();
        entityList.forEach(e -> {
            String label = taskLabelDao.selectUserLabel(e.getUserId());
            if (StrUtil.isNotBlank(label) && label.contains(userLabel)) {
                e.setUserLabel(label);
                list1.add(e);
            } else {
                list2.add(e);
            }
        });

        list1.addAll(list2);
        return list1;
    }

    @Override
    public List<TaskBean> serviceTaskQueryByUserId(String userId) {
        List<TaskEntity> entityList = taskDao.selectListByUserId(userId);

        // 将未处理任务排在最前面
        entityList.sort((a, b) -> a.getOperateStatus() == R.operateStatus.INIT ? -1 :
                (b.getOperateStatus() == R.operateStatus.INIT ? 1 : 0));

        List<TaskBean> beanList = new ArrayList<>();
        entityList.forEach(entity -> {
            TaskBean bean = YYlcBeanUtils.copyProperties(entity, new TaskBean());
            bean.setUserInfo(userBasicDataDao.selectByUserId(bean.getUserId()));

            beanList.add(bean);
        });

        return beanList;
    }

    @Override
    public PageBean<TaskBean> getWaitAllotList(int allotStatus, String userType, String taskCode, int current, int pageSize) {

        Integer operateStatus = R.operateStatus.INIT;
        if (allotStatus == R.allotStatus.FINISH) {
            // 已经分配给客服人员了
            operateStatus = null;
        }

        int total = taskDao.selectByUserTypeCount(R.userType.YYLC, allotStatus, operateStatus, taskCode);
        if (!PageUtil.check(current, total, pageSize)) {
            throw new RuntimeException("页数错误");
        }

        List<TaskEntity> entityList = taskDao.selectByUserType(userType, allotStatus, operateStatus, taskCode,
                PageUtil.getStart(current, pageSize), pageSize);
        List<TaskBean> beanList = new ArrayList<>();
        entityList.forEach(entity -> {
            TaskBean bean = YYlcBeanUtils.copyProperties(entity, new TaskBean());
            bean.setUserInfo(userBasicDataDao.selectByUserId(bean.getUserId()));

            beanList.add(bean);
        });

        return new PageBean<>(current, pageSize, total, beanList);
    }

    public int updateTask(TaskBean bean) {

        logger.info("updateTask bean={}", bean.getId());
        taskDao.update(YYlcBeanUtils.copyProperties(bean, new TaskEntity()));
        logger.info("updateTask bean={} success", bean.getId());
        return 0;
    }


    public List<TaskLabelBean> getTaskLabelList(String taskCode, String labelName) {
        List<TaskLabelEntity> entityList = taskLabelDao.selectList(taskCode, labelName, R.taskLabelStatus.VALID);
        List<TaskLabelBean> beanList = new ArrayList<>();
        entityList.forEach(entity -> beanList.add(YYlcBeanUtils.copyProperties(entity, new TaskLabelBean())));

        // taskCode为空过滤返回结果，根据labelName过滤
        if (StrUtil.isBlank(taskCode)) {
            Set<String> set = new TreeSet<>();
            return beanList.stream().filter(bean -> set.add(bean.getLabelName())).collect(toList());
        }

        return beanList;
    }

    public List<String> getUserLabelList() {
        return taskLabelDao.selectUserLabelList();
    }

    public List<String> getUserLabel(String userId) {
        return StrUtil.split(taskLabelDao.selectUserLabel(userId), R.flag);
    }

    @Transactional
    public int updateUserLabel(String label, String userId) {
        int result = taskLabelDao.updateUserLabel(label, userId);
        if (result == 0) {
            result = taskLabelDao.insertUserLabel(label, userId);
        }

        return result > 0 ? 0 : -1;
    }

    @Override
    public List<List<String>> getChannelList(String serviceId) {
        if (StrUtil.isBlank(serviceId) || customerDao.select(serviceId).isAdmin()) {
            serviceId = null;
        }

        return CollectionUtil.newArrayList(
                userBasicDataDao.getRegisterFromNameList(serviceId).stream().distinct().collect(toList()),
                userBasicDataDao.getRegisterDeviceFromNameList(serviceId).stream().distinct().collect(toList()));
    }

    @Override
    public Object recycleCustomerTask(String customerId) throws Exception {
        CustomerEntity entity = customerDao.select(customerId);
        if (entity == null) {
            throw new Exception("未找到该客服人员信息");
        }

        List<String> deletedUserIdList = new ArrayList<>();
        taskRelationDao.selectWhList(R.whLabel.WEI_WAI_HU).forEach(item -> {
            if (StrUtil.equals(item.getServiceId(), customerId)) {
                taskRelationDao.deleteByIdAndWhLabel(item);
                deletedUserIdList.add(item.getUserId());
            }
        });

        logger.info("recycle customer task, recycle user num={}, userId list={}",
                deletedUserIdList.size(), deletedUserIdList);
        return deletedUserIdList.size();
    }

    @Override
    public Object getCategoryList(String parentId) {
        return getCategoryListInternal(parentId);
    }

    private List<Option> getCategoryListInternal(String parentId) {
        List<Category> list = taskDao.selectCategoryList(parentId);
        if (CollectionUtils.isEmpty(list)) {
            return new ArrayList<>();
        }

        List<Option> result = new ArrayList<>();
        for (Category item : list) {
            List<Option> childList = getCategoryListInternal(item.getCode());
            if (CollectionUtils.isEmpty(childList)) {
                result.add(new Option(item.getCode(), item.getName()));
            } else {
                result.add(new Option2(item.getCode(), item.getName(), childList));
            }
        }
        return result;
    }

    @Data
    @NoArgsConstructor
    @AllArgsConstructor
    static class Option {
        private String value = "";
        private String label = "";
    }

    @Data
    @NoArgsConstructor
    @AllArgsConstructor
    static class Option2 extends Option {
        List<Option> children = new ArrayList<>();

        public Option2(String value, String label, List<Option> children) {
            super(value, label);
            this.children = children;
        }
    }

}
